package com.hmall.gateway.filters;

import com.hmall.common.exception.UnauthorizedException;
import com.hmall.gateway.config.AuthProperties;
import com.hmall.gateway.utils.JwtTool;
import lombok.RequiredArgsConstructor;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.util.AntPathMatcher;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * @author chanchaw
 * @create 2025-08-05 15:31
 */
@Component
@RequiredArgsConstructor
public class AuthGlobalFilter implements GlobalFilter, Ordered {
    private final AuthProperties authProperties;
    private final JwtTool jwtTool;
    private AntPathMatcher antPathMatcher = new AntPathMatcher();

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        // 1. 获取 request
        ServerHttpRequest request = exchange.getRequest();

        // 2. 不需要鉴权的 uri 直接退出
        if(isExclued(request.getPath().toString())){// 不需要鉴权的 uri
            return chain.filter(exchange);
        }

        // 3. 从 request 中获取 token
        List<String> headers = request.getHeaders().get("authorization");
        String token = "";
        if(headers != null && headers.size() > 0) token = Optional.ofNullable(headers.get(0)).orElse("");

        Long userId = null;
        try{
            userId = jwtTool.parseToken(token);// jwt工具从token中解析获取用户ID
        }catch(UnauthorizedException e){
            ServerHttpResponse res = exchange.getResponse();
            res.setStatusCode(HttpStatus.UNAUTHORIZED);
            return res.setComplete();// 中止请求并返回
        }

        // 向下游微服务传递 user-info
        final String userIdString = userId.toString();
        System.out.println("网关中向下传递用户：" + userIdString);
        ServerWebExchange serverWebExchange = exchange.mutate().request(builder -> builder.header("user-info", userIdString)).build();
        return chain.filter(serverWebExchange);
    }

    private boolean isExclued(String path) {
        List<String> excludePaths = authProperties.getExcludePaths();
        if(excludePaths == null || excludePaths.size() == 0) return false;
        List<String> collect = excludePaths.stream().filter(item -> antPathMatcher.match(item,path)).collect(Collectors.toList());
        return collect.size() > 0 ? true : false;
    }

    @Override
    public int getOrder() {
        return 0;
    }
}
